//
// Created by wangyihu2020 on 2022/6/24.
//
#include <CSR_Matrix.h>
#include <cstdlib>
#include <iostream>
CSR_Matrix::CSR_Matrix(const qp_float* src, qp_int row, qp_int col) {
    m_type = CSR_MATRIX;
    m_maxElm = -1.7e38;
    m_dataSize = 0;
    m_colSize = col;
    m_rowSize = row;

    m_row = (qp_int*)malloc(sizeof(qp_int) * (row + 1) );
    m_col = (qp_int*)calloc(m_maxSize, sizeof(qp_int) );
    m_data = (qp_float*)calloc(m_maxSize, sizeof(qp_float));;
    m_row[0] = 0;
    qp_int count = 0;
    for(int i = 0; i < row; i++){
        for(int j = 0; j < col; j++){
            qp_float elm = src[i * col + j];
            if(elm < m_threshold && elm > -m_threshold) continue;
            else {
                m_maxElm = m_maxElm > elm ? m_maxElm : elm;
                m_data[count] = elm;
                m_col[count++] = j;
                m_dataSize++;
            }
        }
        m_row[i + 1] = count;
    }
//    m_col[col] = m_dataSize - 1;
}

CSR_Matrix::CSR_Matrix(qp_int row, qp_int col) {
    m_type = CSR_MATRIX;
    m_maxElm = -1.7e38;
    m_dataSize = 0;
    m_colSize = col;
    m_rowSize = row;
    m_row = (qp_int*)malloc(sizeof(qp_int) * (row + 1) );
    m_col = (qp_int*)calloc(m_maxSize, sizeof(qp_int) );
    m_data = (qp_float*)calloc(m_maxSize, sizeof(qp_float));;
}

void CSR_Matrix::printRow() const {
    std::cout<<"Row array( size: "<<m_rowSize << ") :"<<std::endl;
    for(int i = 0; i < m_rowSize + 1; i++){
        std::cout<<m_row[i]<<' ';
//        if(i % 10 == 9) std::cout<<std::endl;
    }
    std::cout<<std::endl;
}

void CSR_Matrix::printCol() const {
    std::cout<<"Col array( size: "<<m_dataSize << ") :"<<std::endl;
    for(int i = 0; i < m_dataSize; i++){
        std::cout<<m_col[i]<<' ';
//        if(i % 10 == 9) std::cout<<std::endl;
    }
    std::cout<<std::endl;
}

CSC_Matrix *CSR_Matrix::operator*(const CSC_Matrix& right) {
    if(m_colSize != right.getRowSize())
    {
        std::cout<<"error in CSC_Matrix Multiply"<<std::endl;
        return nullptr;
    }
    CSC_Matrix* res = new CSC_Matrix(m_rowSize, right.getColSize());
    res->writeCol(0, 0);
    qp_int count = 0;
    for(int j = 0; j < right.getColSize(); j++){
        for(int i = 0; i < m_rowSize; i++){
            int k = m_row[i];
            int m = right.getCol()[j];
            qp_float unit = 0;
            for(; k < m_row[i + 1]; k++){
                for(; m < right.getCol()[j + 1]; m++){
                    if(right.getRow()[m] < m_col[k]) continue;
                    else if(right.getRow()[m] > m_col[k]) break;
                    unit += m_data[k] * right.getData()[m];//m==k
                }
            }
            if(unit > m_threshold || unit < -m_threshold){
                res->writeData(count, unit);
                res->writeRow(count++, i);//i-th row
            }
        }
        res->writeCol(j + 1, count);
    }
    res->setDataSize(count);
//    return nullptr;
}



CSR_Matrix::CSR_Matrix() = default;


#include "CSR_Matrix.h"
